package com.moss.cloud.common.flow.parser;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.moss.cloud.common.core.utils.BooleanHandel;
import com.moss.cloud.common.core.utils.JSONUtil;
import com.moss.cloud.common.flow.enums.TaskType;
import com.moss.cloud.common.flow.model.*;
import org.apache.commons.collections4.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public class TaskParser {
    public static void main(String[] args) {
        String jsonStr = "{\"cells\":[{\"shape\":\"data-processing-curve\",\"connector\":{\"name\":\"curveConnector\"},\"attrs\":{\"line\":{\"stroke\":\"#3471F9\",\"strokeDasharray\":5,\"style\":{\"animation\":\"running-line 30s infinite linear\"}}},\"id\":\"760cea0c-c220-4409-a3f3-ba8d1450737a\",\"zIndex\":-1,\"data\":{\"source\":\"node-start\",\"target\":\"587f9e6f-ba63-4781-8ffb-eaf47aaed2df\"},\"source\":{\"cell\":\"node-start\",\"port\":\"node-start-out\"},\"target\":{\"cell\":\"587f9e6f-ba63-4781-8ffb-eaf47aaed2df\",\"port\":\"587f9e6f-ba63-4781-8ffb-eaf47aaed2df-in\"}},{\"shape\":\"data-processing-curve\",\"connector\":{\"name\":\"curveConnector\"},\"attrs\":{\"line\":{\"stroke\":\"#3471F9\",\"strokeDasharray\":5,\"style\":{\"animation\":\"running-line 30s infinite linear\"}}},\"id\":\"fd156f5d-df4b-4b78-8ea0-3aa17b367488\",\"zIndex\":-1,\"data\":{\"source\":\"node-start\",\"target\":\"9a7027b6-d6e8-4d4e-b220-e256f5d81127\"},\"source\":{\"cell\":\"node-start\",\"port\":\"node-start-out\"},\"target\":{\"cell\":\"9a7027b6-d6e8-4d4e-b220-e256f5d81127\",\"port\":\"9a7027b6-d6e8-4d4e-b220-e256f5d81127-in\"}},{\"shape\":\"data-processing-curve\",\"connector\":{\"name\":\"curveConnector\"},\"attrs\":{\"line\":{\"stroke\":\"#3471F9\",\"strokeDasharray\":5,\"style\":{\"animation\":\"running-line 30s infinite linear\"}}},\"id\":\"eea7a702-f70d-40dd-b513-308a62ec6d38\",\"zIndex\":-1,\"data\":{\"source\":\"587f9e6f-ba63-4781-8ffb-eaf47aaed2df\",\"target\":\"1fcb687f-9075-4e6a-8ecb-4072b68998d3\"},\"source\":{\"cell\":\"587f9e6f-ba63-4781-8ffb-eaf47aaed2df\",\"port\":\"587f9e6f-ba63-4781-8ffb-eaf47aaed2df-out\"},\"target\":{\"cell\":\"1fcb687f-9075-4e6a-8ecb-4072b68998d3\",\"port\":\"1fcb687f-9075-4e6a-8ecb-4072b68998d3-in\"}},{\"shape\":\"data-processing-curve\",\"connector\":{\"name\":\"curveConnector\"},\"attrs\":{\"line\":{\"stroke\":\"#3471F9\",\"strokeDasharray\":5,\"style\":{\"animation\":\"running-line 30s infinite linear\"}}},\"id\":\"75f39ae6-21da-40bb-9211-1d09f05f616b\",\"zIndex\":-1,\"data\":{\"source\":\"9a7027b6-d6e8-4d4e-b220-e256f5d81127\",\"target\":\"98684ae0-11ec-44ff-a1f7-047ff21f8243\"},\"source\":{\"cell\":\"9a7027b6-d6e8-4d4e-b220-e256f5d81127\",\"port\":\"9a7027b6-d6e8-4d4e-b220-e256f5d81127-out\"},\"target\":{\"cell\":\"98684ae0-11ec-44ff-a1f7-047ff21f8243\",\"port\":\"98684ae0-11ec-44ff-a1f7-047ff21f8243-in\"}},{\"shape\":\"data-processing-curve\",\"connector\":{\"name\":\"curveConnector\"},\"attrs\":{\"line\":{\"stroke\":\"#3471F9\",\"strokeDasharray\":5,\"style\":{\"animation\":\"running-line 30s infinite linear\"}}},\"id\":\"c08312e4-535c-4301-9288-03e8427efcda\",\"zIndex\":-1,\"data\":{\"source\":\"1fcb687f-9075-4e6a-8ecb-4072b68998d3\",\"target\":\"node-merge\"},\"source\":{\"cell\":\"1fcb687f-9075-4e6a-8ecb-4072b68998d3\",\"port\":\"1fcb687f-9075-4e6a-8ecb-4072b68998d3-out\"},\"target\":{\"cell\":\"node-merge\",\"port\":\"node-merge-in\"}},{\"shape\":\"data-processing-curve\",\"connector\":{\"name\":\"curveConnector\"},\"attrs\":{\"line\":{\"stroke\":\"#3471F9\",\"strokeDasharray\":5,\"style\":{\"animation\":\"running-line 30s infinite linear\"}}},\"id\":\"8a9eeb98-4949-4cb8-9290-2f85b8ce0901\",\"zIndex\":-1,\"data\":{\"source\":\"98684ae0-11ec-44ff-a1f7-047ff21f8243\",\"target\":\"node-merge\"},\"source\":{\"cell\":\"98684ae0-11ec-44ff-a1f7-047ff21f8243\",\"port\":\"98684ae0-11ec-44ff-a1f7-047ff21f8243-out\"},\"target\":{\"cell\":\"node-merge\",\"port\":\"node-merge-in\"}},{\"shape\":\"data-processing-curve\",\"connector\":{\"name\":\"curveConnector\"},\"attrs\":{\"line\":{\"stroke\":\"#3471F9\",\"strokeDasharray\":5,\"style\":{\"animation\":\"running-line 30s infinite linear\"}}},\"id\":\"60361d00-1c12-493f-8f35-ab7e6395e3fc\",\"zIndex\":-1,\"data\":{\"source\":\"node-merge\",\"target\":\"node-end\"},\"source\":{\"cell\":\"node-merge\",\"port\":\"node-merge-out\"},\"target\":{\"cell\":\"node-end\",\"port\":\"node-end-in\"}},{\"position\":{\"x\":-320,\"y\":-100},\"size\":{\"width\":212,\"height\":48},\"view\":\"vue-shape-view\",\"shape\":\"data-processing-dag-node\",\"data\":{\"name\":\"开始\",\"type\":\"START\",\"checkStatus\":\"sucess\",\"status\":\"success\"},\"ports\":{\"groups\":{\"in\":{\"position\":\"left\",\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}},\"out\":{\"position\":{\"name\":\"right\",\"args\":{\"dx\":-32}},\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}}},\"items\":[{\"id\":\"node-start-out\",\"group\":\"out\"}]},\"id\":\"node-start\",\"zIndex\":1},{\"position\":{\"x\":-70,\"y\":-100},\"size\":{\"width\":212,\"height\":48},\"view\":\"vue-shape-view\",\"shape\":\"data-processing-dag-node\",\"data\":{\"name\":\"请假天数>3\",\"type\":\"CONDITION\",\"condition\":{\"field\":\"days\",\"conditionValue\":\"3\",\"term\":\">\",\"desc\":\"请假天数\"}},\"ports\":{\"groups\":{\"in\":{\"position\":\"left\",\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}},\"out\":{\"position\":{\"name\":\"right\",\"args\":{\"dx\":-32}},\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}}},\"items\":[{\"id\":\"587f9e6f-ba63-4781-8ffb-eaf47aaed2df-in\",\"group\":\"in\"},{\"id\":\"587f9e6f-ba63-4781-8ffb-eaf47aaed2df-out\",\"group\":\"out\"}]},\"id\":\"587f9e6f-ba63-4781-8ffb-eaf47aaed2df\",\"zIndex\":2,\"tools\":{\"items\":[{\"name\":\"button-remove\",\"args\":{\"x\":200,\"y\":10}}]}},{\"position\":{\"x\":-70,\"y\":0},\"size\":{\"width\":212,\"height\":48},\"view\":\"vue-shape-view\",\"shape\":\"data-processing-dag-node\",\"data\":{\"name\":\"请假天数>=3\",\"type\":\"CONDITION\",\"condition\":{\"field\":\"days\",\"conditionValue\":\"3\",\"term\":\">=\",\"desc\":\"请假天数\"}},\"ports\":{\"groups\":{\"in\":{\"position\":\"left\",\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}},\"out\":{\"position\":{\"name\":\"right\",\"args\":{\"dx\":-32}},\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}}},\"items\":[{\"id\":\"9a7027b6-d6e8-4d4e-b220-e256f5d81127-in\",\"group\":\"in\"},{\"id\":\"9a7027b6-d6e8-4d4e-b220-e256f5d81127-out\",\"group\":\"out\"}]},\"id\":\"9a7027b6-d6e8-4d4e-b220-e256f5d81127\",\"zIndex\":3,\"tools\":{\"items\":[{\"name\":\"button-remove\",\"args\":{\"x\":200,\"y\":10}}]}},{\"position\":{\"x\":180,\"y\":-100},\"size\":{\"width\":212,\"height\":48},\"view\":\"vue-shape-view\",\"shape\":\"data-processing-dag-node\",\"data\":{\"name\":\"部门经理审批\",\"type\":\"TASK\",\"headUser\":[101],\"ccToUser\":[101],\"nodeTaskEndTime\":null,\"reachEndTimePass\":false,\"sign\":\"OR\",\"condition\":{\"field\":\"\",\"conditionValue\":\"\",\"term\":\"\",\"desc\":\"\"}},\"ports\":{\"groups\":{\"in\":{\"position\":\"left\",\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}},\"out\":{\"position\":{\"name\":\"right\",\"args\":{\"dx\":-32}},\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}}},\"items\":[{\"id\":\"1fcb687f-9075-4e6a-8ecb-4072b68998d3-in\",\"group\":\"in\"},{\"id\":\"1fcb687f-9075-4e6a-8ecb-4072b68998d3-out\",\"group\":\"out\"}]},\"id\":\"1fcb687f-9075-4e6a-8ecb-4072b68998d3\",\"zIndex\":4,\"tools\":{\"items\":[{\"name\":\"button-remove\",\"args\":{\"x\":200,\"y\":10}}]}},{\"position\":{\"x\":180,\"y\":0},\"size\":{\"width\":212,\"height\":48},\"view\":\"vue-shape-view\",\"shape\":\"data-processing-dag-node\",\"data\":{\"name\":\"组长审批\",\"type\":\"TASK\",\"headUser\":[102],\"ccToUser\":[101],\"nodeTaskEndTime\":null,\"reachEndTimePass\":false,\"sign\":\"OR\",\"condition\":{\"field\":\"\",\"conditionValue\":\"\",\"term\":\"\",\"desc\":\"\"}},\"ports\":{\"groups\":{\"in\":{\"position\":\"left\",\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}},\"out\":{\"position\":{\"name\":\"right\",\"args\":{\"dx\":-32}},\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}}},\"items\":[{\"id\":\"98684ae0-11ec-44ff-a1f7-047ff21f8243-in\",\"group\":\"in\"},{\"id\":\"98684ae0-11ec-44ff-a1f7-047ff21f8243-out\",\"group\":\"out\"}]},\"id\":\"98684ae0-11ec-44ff-a1f7-047ff21f8243\",\"zIndex\":5,\"tools\":{\"items\":[{\"name\":\"button-remove\",\"args\":{\"x\":200,\"y\":10}}]}},{\"position\":{\"x\":430,\"y\":-100},\"size\":{\"width\":212,\"height\":48},\"view\":\"vue-shape-view\",\"shape\":\"data-processing-dag-node\",\"data\":{\"name\":\"人事审批\",\"type\":\"MERGE\",\"headUser\":[101],\"ccToUser\":[101],\"nodeTaskEndTime\":null,\"reachEndTimePass\":false,\"sign\":\"OR\",\"condition\":{\"field\":\"\",\"conditionValue\":\"\",\"term\":\"\",\"desc\":\"\"}},\"ports\":{\"groups\":{\"in\":{\"position\":\"left\",\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}},\"out\":{\"position\":{\"name\":\"right\",\"args\":{\"dx\":-32}},\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}}},\"items\":[{\"id\":\"node-merge-in\",\"group\":\"in\"},{\"id\":\"node-merge-out\",\"group\":\"out\"}]},\"id\":\"node-merge\",\"zIndex\":6,\"tools\":{\"items\":[{\"name\":\"button-remove\",\"args\":{\"x\":200,\"y\":10}}]}},{\"position\":{\"x\":680,\"y\":-100},\"size\":{\"width\":212,\"height\":48},\"view\":\"vue-shape-view\",\"shape\":\"data-processing-dag-node\",\"data\":{\"name\":\"结束\",\"type\":\"END\"},\"ports\":{\"groups\":{\"in\":{\"position\":\"left\",\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}},\"out\":{\"position\":{\"name\":\"right\",\"args\":{\"dx\":-32}},\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}}},\"items\":[{\"id\":\"node-end-in\",\"group\":\"in\"}]},\"id\":\"node-end\",\"zIndex\":7,\"tools\":{\"items\":[{\"name\":\"button-remove\",\"args\":{\"x\":200,\"y\":10}}]}}]}";
        String flowJson = "{\"list\":[{\"label\":\"请假天数\",\"type\":\"number\",\"options\":{\"change\":\"\",\"showLabel\":true,\"width\":\"100%\",\"defaultValue\":4,\"min\":0,\"max\":100,\"step\":1,\"readonly\":false,\"disabled\":false,\"rules\":{\"trigger\":\"blur\",\"enum\":\"\",\"message\":\"\",\"pattern\":\"\",\"required\":true,\"type\":\"number\"}},\"key\":\"6f7486fe5471401a9a5c5955774b6e9e\",\"model\":\"days\",\"rules\":[]},{\"label\":\"请假事由\",\"type\":\"input\",\"options\":{\"change\":\"\",\"width\":\"100%\",\"type\":\"textarea\",\"showLabel\":true,\"defaultValue\":\"请假啊\",\"placeholder\":\"请输入请假事由\",\"maxlength\":null,\"showCount\":false,\"prefix\":\"\",\"suffix\":\"\",\"disabled\":false,\"allowClear\":false,\"readonly\":false,\"round\":false,\"rules\":{\"trigger\":\"blur\",\"enum\":\"\",\"message\":\"\",\"pattern\":\"\",\"required\":true,\"type\":\"string\"}},\"key\":\"30b2be88e41e45ab97602f0aab6d016e\",\"model\":\"desc\",\"rules\":[]}],\"config\":{\"size\":\"medium\",\"hideRequiredMark\":false,\"groupType\":\"radioGroup\",\"inline\":false,\"labelAlign\":\"left\",\"labelWidth\":\"auto\",\"labelPlacement\":\"top\",\"showLabel\":true}}";
        System.out.println(JSONObject.toJSONString(taskNodes(jsonStr, flowJson)));
    }

    /**
     * 获取任务节点数据
     *
     * @param taskJson     完整任务节点JSON数据
     * @param flowFormJson 流程动态表单JSON数据
     * @return List<NodeTask>
     */
    public static List<NodeTask> taskNodes(String taskJson, String flowFormJson) {
        FlowData flowData = JSONUtil.toJavaBean(flowFormJson, FlowData.class);
        List<NodeTask> nodeTasks = FlowParser.nodeTasks(taskJson);
        List<NodeRelation> nodeRelations = FlowParser.relationList(taskJson);
        // List<NodeTask>中的条件对象为空，或者，动态流程表单数据为空都返回原始流程任务结构
        boolean conditionIsEmpty = nodeTasks.stream().filter(item -> TaskType.CONDITION.getType().equals(item.getType()))
                .anyMatch(item -> Objects.isNull(item.getCondition()));
        return Objects.nonNull(flowData) && !conditionIsEmpty ? filteredNodeTasks(nodeTasks, nodeRelations, flowData) :
                nodeTasks.stream().filter(item -> !(TaskType.START.getType().equals(item.getType()) || TaskType.END.getType().equals(item.getType())))
                        .collect(Collectors.toList());
    }

    /**
     * 解析符合条件的流程任务数据
     *
     * @param nodeTasks     流程模型完整数据
     * @param nodeRelations 节点关系数据
     * @param flowData      流程动态表单数据
     * @return List<NodeTask>
     */
    private static List<NodeTask> filteredNodeTasks(List<NodeTask> nodeTasks, List<NodeRelation> nodeRelations, FlowData flowData) {
        List<NodeTask> filteredNodeTasks = new ArrayList<>();
        nodeTasks.forEach(item -> {
            BooleanHandel.isTrue(TaskType.CONDITION.getType().equals(item.getType()))
                    .trueHandle(() -> conditionParser(nodeTasks, item, nodeRelations, flowData, filteredNodeTasks));
            BooleanHandel.isTrue(TaskType.TASK.getType().equals(item.getType()))
                    .trueHandle(() -> taskParser(filteredNodeTasks, nodeRelations, nodeTasks));
        });
        filteredNodeTasks.removeIf(item -> item.getType().equals(TaskType.END.getType()));
        return filteredNodeTasks;
    }

    /**
     * 条件节点处理
     *
     * @param nodeTasks         流程模型完整数据
     * @param nodeTask          当前正在解析的节点
     * @param nodeRelations     节点关系数据
     * @param flowData          流程动态表单数据
     * @param filteredNodeTasks 符合条件的节点容器
     */
    private static void conditionParser(List<NodeTask> nodeTasks, NodeTask nodeTask, List<NodeRelation> nodeRelations,
                                        FlowData flowData, List<NodeTask> filteredNodeTasks) {
        FlowForm flowForm = flowData.getList().stream().filter(a -> a.getModel().equals(nodeTask.getCondition().getField())).findFirst().orElse(null);
        int b = Integer.parseInt(((JSONObject) JSON.toJSON(flowForm.getOptions())).getString("defaultValue"));
        switch (nodeTask.getCondition().getTerm()) {
            case ">":
                if (b > Integer.parseInt(nodeTask.getCondition().getConditionValue())) {
                    addFilteredNodeTasks(nodeTasks, nodeRelations, nodeTask, filteredNodeTasks);
                }
                break;
            case "<=":
                if (b <= Integer.parseInt(nodeTask.getCondition().getConditionValue())) {
                    addFilteredNodeTasks(nodeTasks, nodeRelations, nodeTask, filteredNodeTasks);
                }
                break;
        }
    }

    /**
     * 添加符合条件的节点
     *
     * @param nodeTasks         流程模型完整数据
     * @param nodeRelations     节点关系数据
     * @param nodeTask          当前正在解析的节点
     * @param filteredNodeTasks 符合条件的节点容器
     */
    private static void addFilteredNodeTasks(List<NodeTask> nodeTasks, List<NodeRelation> nodeRelations, NodeTask nodeTask, List<NodeTask> filteredNodeTasks) {
        nodeRelations.forEach(x -> {
            if (x.getSource().equals(nodeTask.getTaskId())) {
                NodeTask result = nodeTasks.stream()
                        .filter(task -> x.getTarget().equals(task.getTaskId()))
                        .findFirst()
                        .orElse(null);
                Objects.requireNonNull(result).setTarget(nodeRelations.stream()
                        .filter(node -> x.getTarget().equals(node.getSource()))
                        .map(NodeRelation::getTarget)
                        .findFirst()
                        .orElse(""));
                filteredNodeTasks.add(result);
            }
        });
    }

    /**
     * 其他节点处理
     *
     * @param filteredNodeTasks 符合条件的节点容器
     * @param nodeRelations     节点关系数据
     * @param nodeTasks         流程模型完整数据
     */
    private static void taskParser(List<NodeTask> filteredNodeTasks, List<NodeRelation> nodeRelations, List<NodeTask> nodeTasks) {
        BooleanHandel.isTrue(CollectionUtils.isNotEmpty(filteredNodeTasks)).trueHandle(() -> {
            String source = filteredNodeTasks.get(filteredNodeTasks.size() - 1).getTaskId();
            nodeRelations.forEach(x -> {
                if (source.equals(x.getSource())) {
                    NodeTask result = nodeTasks.stream()
                            .filter(nodeTask -> x.getTarget().equals(nodeTask.getTaskId()))
                            .findFirst()
                            .orElse(null);
                    Objects.requireNonNull(result).setTarget(nodeRelations.stream()
                            .filter(node -> x.getTarget().equals(node.getSource()))
                            .map(NodeRelation::getTarget)
                            .findFirst()
                            .orElse(""));
                    filteredNodeTasks.add(result);
                }
            });
        });
    }
}
